package com.conversationboard.keygenerator;

import java.sql.SQLException;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import com.conversationboard.logger.LogMessageType;
import com.conversationboard.logger.Logger;
import com.conversationboard.site.AutoNumber;

/** Used as an alternative to MySQL's autoincrement function. This makes it easier to port between database
 * architectures, e.g. InnoDB; Falcon etc. It works by only returning you a unique ID, which is initialised
 * with the maximum values in the database at startup time.
 * 
 * The values as integers and as such will overflow at 2,000,000,000. At the risk of making a gaffe I will
 * assume that no message board is going to have this many posts in it for a long time.
 * 
 * These are AtomicInteger objects, which do not need synchronised.
 * 
 * The get methods throw a KeyGeneratorNotInitialisedException. StartupControllerServlet sets the initialised
 * flag once it is happy that it has successfully read the database to get the maximum key values. This is to
 * prevent anyone writing anything relying on these to the database if the initialisation didn't work
 * successfully.
 * 
 * Updated Dec 2011 to lazily get the latest autonumber key from the database to speed up reloading of the web
 * application whilst doing development.
 * 
 * @author Keith Watson */

public class KeyGenerator {

	private static AtomicInteger threadKey = new AtomicInteger();
	private static AtomicInteger messageKey = new AtomicInteger();
	private static boolean successfullyInitialised = false;


	public static boolean isSuccessfullyInitialised() {
		return successfullyInitialised;
	}


	public static void setSuccessfullyInitialised(boolean successfullyInitialised) {
		KeyGenerator.successfullyInitialised = successfullyInitialised;
	}


	public static int getThreadKey() throws KeyGeneratorNotInitialisedException, SQLException {

		if (!successfullyInitialised) {

			AutoNumber.initialiseAutoNumbers();

			if (!successfullyInitialised) {
				throw new KeyGeneratorNotInitialisedException();
			}
		}

		return threadKey.incrementAndGet();
	}


	public static int getMessageKey() throws KeyGeneratorNotInitialisedException, SQLException {

		if (!successfullyInitialised) {
			AutoNumber.initialiseAutoNumbers();

			if (!successfullyInitialised) {
				throw new KeyGeneratorNotInitialisedException();
			}
		}
		return messageKey.incrementAndGet();
	}


	public static void setThreadKey(int initialValue) {
		Logger.log(new Date(), "Maximum thread key: " + initialValue, null, LogMessageType.SERVER);
		threadKey.set(initialValue);
	}


	public static void setMessageKey(int initialValue) {
		Logger.log(new Date(), "Maximum message key: " + initialValue, null, LogMessageType.SERVER);
		messageKey.set(initialValue);
	}

}
